﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data.Objects.DataClasses;
using System.IO;
using System.Drawing;
using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;

namespace GoDive.Common
{
    public class Utility
    {
        #region 属性，字段
        //DEC密匙
        private static string DECKey = "nmf#gfs*fsa@Vhts";
        #endregion

        public static void UpdateEffectiveField(EntityObject originalObj, EntityObject newObj)
        {
            Type type = originalObj.GetType();
            var properties = type.GetProperties();

            foreach (PropertyInfo item in properties)
            {
                string name = item.Name;
                if (name == "EntityKey" || name == "EntityState")
                {
                    continue;
                }

                object newValue = item.GetValue(newObj, null);
                object originalValue = item.GetValue(originalObj, null);

                if (item.PropertyType.FullName == "System.DateTime"
                    && newValue.Equals(new DateTime()))
                {
                    continue;
                }

                if (newValue != null && !newValue.Equals(originalValue))
                {
                    item.SetValue(originalObj, newValue, null);
                }
            }
        }

        public static void UpdateEffectiveField<T>(T originalObj, T newObj)
        {
            Type type = originalObj.GetType();
            var properties = type.GetProperties();

            foreach (PropertyInfo item in properties)
            {
                object newValue = item.GetValue(newObj, null);
                object originalValue = item.GetValue(originalObj, null);

                if (item.PropertyType.FullName == "System.DateTime"
                    && newValue.Equals(new DateTime()))
                {
                    continue;
                }

                if (newValue != null && !newValue.Equals(originalValue))
                {
                    item.SetValue(originalObj, newValue, null);
                }
            }
        }

        public static long GetUnixDate(DateTime? date = null)
        {
            if (date == null)
            {
                date = DateTime.Now;
            }
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            TimeSpan toNow = date.Value.Subtract(dtStart);
            string timeStamp = toNow.Ticks.ToString();
            timeStamp = timeStamp.Substring(0, timeStamp.Length - 7);
            return long.Parse(timeStamp);
        }

        public static DateTime GetDateFromUnixDate(long unixdate)
        {
            //将UNIX时间戳转换成系统时间 
            string timeStamp = unixdate.ToString();
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            DateTime dtResult = dtStart.Add(toNow);
            return dtResult;
        }

        public static string MD5(string text)
        {
            string sResult = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(text, "MD5");
            return sResult;
        }

        #region 删除指定名称Cookie
        public static void RemoveCookie(string cookieName)
        {
            HttpCookie hc = HttpContext.Current.Request.Cookies[cookieName]; //XXXX为Cookie的名字
            if (hc != null)
                hc.Expires = DateTime.Now.AddDays(-1); //设置过期时间为过去的某个时间
            HttpContext.Current.Response.Cookies.Add(hc); //覆盖客户端的同名Cookie
        }
        #endregion

        #region 将对象序列化后添加到指定Cookie
        /// <summary>
        /// 添加Cookie对象并序列化
        /// </summary>
        /// <param name="obj">需进行序列化的对象</param>
        /// <param name="obj">cookie名称</param>
        /// <returns>返回二进制字符串</returns>
        public static string SetCookie(object obj, string cookiename)
        {
            BinaryFormatter bf = new BinaryFormatter();  //声明一个序列化类
            MemoryStream ms = new MemoryStream();  //声明一个内存流
            bf.Serialize(ms, obj);  //执行序列化操作
            byte[] result = new byte[ms.Length];
            result = ms.ToArray();
            string temp = System.Convert.ToBase64String(result);
            temp = Encrypt(temp);
            HttpCookie cookie = new HttpCookie(cookiename);
            cookie.HttpOnly = true;
            cookie.Value = temp;
            HttpContext.Current.Response.Cookies.Set(cookie);
            ms.Flush();
            ms.Close();
            return temp;
        }
        public static void SetCookie(string str, string cookiename)
        {
            HttpCookie cookie = new HttpCookie(cookiename);
            cookie.HttpOnly = true;
            cookie.Value = str;
            HttpContext.Current.Response.Cookies.Set(cookie);
        }
        #endregion

        #region 获取Cookie对象并反序列化为指定类型
        /// <summary>
        /// 获取Cookie对象并序列化
        /// </summary>
        /// <param name="cookiename">cookie名称</param>
        /// <returns>反序列化后的Object对象</returns>
        public static T GetObjFromCookie<T>(string cookiename)
        {
            if (HttpContext.Current.Request.Cookies[cookiename] != null)
            {
                try
                {
                    string temp = HttpContext.Current.Request.Cookies[cookiename].Value;
                    temp = Decrypt(temp);
                    byte[] b = System.Convert.FromBase64String(temp);  //将得到的字符串根据相同的编码格式分成字节数组
                    MemoryStream msb = new MemoryStream(b, 0, b.Length);  //从字节数组中得到内存流
                    BinaryFormatter bfb = new BinaryFormatter();
                    return (T)bfb.Deserialize(msb);  //返回Object对象
                }
                catch (Exception)
                {
                    return default(T);
                }
            }
            else
            {
                return default(T);
            }
        }

        public static string GetCookie(string name)
        {
            return HttpContext.Current.Request.Cookies[name].Value;
        }

        public static string ValidateCodeEncrypt(string authStr)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] bytes = UTF8Encoding.UTF8.GetBytes(authStr.ToLower());
            byte[] hashBytes = md5.ComputeHash(bytes);
            string md5Cookie = Convert.ToBase64String(hashBytes);
            return md5Cookie;
        }
        #endregion

        #region 原DEC 加密过程

        /// <summary>
        /// DEC 加密过程
        /// </summary>
        /// <param name="strValue">被加密的字符串</param> 
        /// <returns>加密后的字符串</returns>
        public static string Encrypt(string strValue)
        {
            //访问数据加密标准(DES)算法的加密服务提供程序 (CSP) 版本的包装对象
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            des.Key = ASCIIEncoding.ASCII.GetBytes(DECKey.Substring(0, 8));　//建立加密对象的密钥和偏移量
            des.IV = ASCIIEncoding.ASCII.GetBytes(DECKey.Insert(0, "w").Substring(0, 8));　 //原文使用ASCIIEncoding.ASCII方法的GetBytes方法

            byte[] inputByteArray = Encoding.Default.GetBytes(strValue);//把字符串放到byte数组中

            MemoryStream ms = new MemoryStream();//创建其支持存储区为内存的流　
            //定义将数据流链接到加密转换的流
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            //上面已经完成了把加密后的结果放到内存中去

            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                ret.AppendFormat("{0:X2}", b);
            }
            ret.ToString();
            return ret.ToString();
        }
        #endregion

        #region  原DEC 解密过程

        /// <summary>
        /// DEC 解密过程
        /// </summary>
        /// <param name="EncValue">被解密的字符串</param>  
        /// <returns>返回被解密的字符串</returns>
        public static string Decrypt(string EncValue)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = new byte[EncValue.Length / 2];
            for (int x = 0; x < EncValue.Length / 2; x++)
            {
                int i = (Convert.ToInt32(EncValue.Substring(x * 2, 2), 16));
                inputByteArray[x] = (byte)i;
            }

            des.Key = ASCIIEncoding.ASCII.GetBytes(DECKey.Substring(0, 8));　//建立加密对象的密钥和偏移量，此值重要，不能修改
            des.IV = ASCIIEncoding.ASCII.GetBytes(DECKey.Insert(0, "w").Substring(0, 8));
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);

            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();

            //建立StringBuild对象，createDecrypt使用的是流对象，必须把解密后的文本变成流对象
            StringBuilder ret = new StringBuilder();

            return System.Text.Encoding.Default.GetString(ms.ToArray());
        }
        #endregion

        public static System.Drawing.Image GetImageFromBytes(byte[] streamByte)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream(streamByte);
            System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
            return img;
        }

        public static string GetImageFomat(System.Drawing.Image imgSrc)
        {
            string strImgFormat = "";
            if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
                strImgFormat = "jpeg";
            else if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
                strImgFormat = "gif";
            else if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
                strImgFormat = "bmp";
            else if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
                strImgFormat = "png";
            else if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
                strImgFormat = "tiff";
            else if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Icon))
                strImgFormat = "icon";
            else if (imgSrc.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Wmf))
                strImgFormat = "wmf";
            return strImgFormat;
        }

        public static byte[] GetBytesFromImage(string imagepath)
        {
            byte[] data = null;
            Image img = Image.FromFile(imagepath);
            using (MemoryStream ms = new MemoryStream())
            {
                using (Bitmap Bitmap = new Bitmap(img))
                {
                    Bitmap.Save(ms, img.RawFormat);
                    ms.Position = 0;
                    data = new byte[ms.Length];
                    ms.Read(data, 0, Convert.ToInt32(ms.Length));
                    ms.Flush();
                }
            }
            return data;
        }


        ///<summary>
        /// 根据 Agent 判断是否为移动设备
        ///</summary>
        ///<returns></returns>
        public static bool IsMobileDevice()
        {
            bool flag = false;

            string agent = HttpContext.Current.Request.UserAgent;
            string[] keywords = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };

            //排除 Windows 桌面系统
            if (!agent.Contains("Windows NT") || (agent.Contains("Windows NT") && agent.Contains("compatible; MSIE 9.0;")))
            {
                //排除 苹果桌面系统
                if (!agent.Contains("Windows NT") && !agent.Contains("Macintosh"))
                {
                    foreach (string item in keywords)
                    {
                        if (agent.Contains(item))
                        {
                            flag = true;
                            break;
                        }
                    }
                }
            }

            return flag;
        }

    }
}
